/*
 * RF12 driver by Krzysztof Kotarski
 * 19.02.2009
 *
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <string.h>
#include "rf12.h"


//fuse configuration avrdude -p m16 -c bsd -U hfuse:w:0xC9:m -U lfuse:w:0xef:m

#define RF12_SDI _BV(PC2) 	//green
#define RF12_SDO _BV(PC1) 	//black
#define RF12_SCK _BV(PC3)	//white
#define RF12_nSEL _BV(PC0)	//yellow
#define RF12_nIRQ _BV(PD2)	//red
#define RF12_nIRQ_PORT PIND
//#define RF12_FFIT _BV(PD2) 	//brown

#define RF12_ET 0x0020

#define SETB(x) (PORTC |= (x))
#define CLRB(x) (PORTC &= ~(x))

#define RF12_STATUS_IDLE	0x00
#define RF12_STATUS_TX		0x01
#define RF12_STATUS_RX		0x02

char preamble[2];
char pattern[2];
char snd_buf[RF12_BUFF_SIZE + 6]; //6byte - 2b preamble, 2b pattern, 2b post preamble
char rcv_buf[RF12_BUFF_SIZE];
char main_buf[32];
volatile int snd_counter = 0;
volatile int rcv_counter = 0;

char rf12_status = RF12_STATUS_IDLE;

volatile int flag;

unsigned int rf12_spi_readwrite(unsigned int data)
{
	int i;
	unsigned int buf=0;
	CLRB(RF12_SCK);
	CLRB(RF12_nSEL);
	for(i=0;i<16;i++)
	{
		if(data & (1<<(15-i))) SETB(RF12_SDI); else CLRB(RF12_SDI);
		SETB(RF12_SCK);
		buf|= ((((PINC & RF12_SDO)!=0)?1:0)<<(15-i));
		CLRB(RF12_SCK);
	}
	SETB(RF12_nSEL);
	return buf;
}

void rf12_init()
{
	int i,j;
	for(i=0; i<10000; i++)
		for(j=0; j<10; j++);

	MCUCR = _BV(ISC01);
	GICR = _BV(INT0);

	DDRC = RF12_SDI|RF12_SCK|RF12_nSEL;

	SETB(RF12_nSEL);
	CLRB(RF12_SCK);

	//printf_P(PSTR("[RF12] Driver started.\n"));
}

inline unsigned int rf12_read_sr()
{
	return rf12_spi_readwrite(0x0000);
}

inline void rf12_fifo_reset()
{
	rf12_spi_readwrite(0xCA81);
	rf12_spi_readwrite(0xCA83);
}

void rf12_dump_sr()
{
	unsigned int sr;
	unsigned int ffit_rgit,por,ffov_rgur,wkup,ext,lbd,ffem,rssi_ats,dqd,crl,atgl;
	int offs;

	printf_P(PSTR("[RF12] Status register dump:\n"));
	sr=rf12_spi_readwrite(0x0000);

	ffit_rgit = (sr & (1<<15))?1:0;
	por = (sr & (1<<14))?1:0;
	ffov_rgur = (sr & (1<<13))?1:0;
	wkup = (sr & (1<<12))?1:0;
	ext = (sr & (1<<11))?1:0;
	lbd = (sr & (1<<10))?1:0;
	ffem = (sr & (1<<9))?1:0;
	rssi_ats = (sr & (1<<8))?1:0;
	dqd = (sr & (1<<7))?1:0;
	crl = (sr & (1<<6))?1:0;
	atgl = (sr & (1<<5))?1:0;
	offs = (-1)*(sr & 1<<4)*(sr & 0x000f);

	printf_P(PSTR("FFIT/RGIT = %d\t\tPOR       = %d\n"),ffit_rgit, por);
	printf_P(PSTR("FFOV/RGUR = %d\t\tWKUP      = %d\n"),ffov_rgur, wkup);
	printf_P(PSTR("EXT       = %d\t\tLBD       = %d\n"),ext, lbd);
	printf_P(PSTR("FFEM      = %d\t\tRSSI/ATS  = %d\n"),ffem, rssi_ats);
	printf_P(PSTR("DQD       = %d\t\tCRL       = %d\n"),dqd, crl);
	printf_P(PSTR("ATGL      = %d\t\tOFFS      = %d\n"),atgl, offs);
}

void rf12_rx_mode(long int baudrate)
{ //skopiowane z Lodz experimental engineering
	unsigned char baud_setting;
	if(baudrate < 3000)
	{
		baud_setting = 43103/baudrate - 1;
		baud_setting |= 0x80;
	}
	else
	{
		baud_setting = 344828/baudrate - 1;
		baud_setting &= 0x7F;
	}

	rf12_spi_readwrite(0x80D7/*& 0xFF3F*/); //EL,EF,433band,12.0pF //ok
	rf12_spi_readwrite(0x8299); //ER,!ebb,!et,ES,EX,!eb,!ew,DC (bug was here) //ok
	rf12_spi_readwrite(0xA640); //frequency select - 434MHz //ok
	rf12_spi_readwrite(0xC600 | baud_setting); //4.8kbps //ok
	//rf12_spi_readwrite(0xC6FF); //0.3kbps //ok
	rf12_spi_readwrite(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm //ok
	rf12_spi_readwrite(0xC2AC); //AL,!ml,DIG,DQD4 //ok
	rf12_spi_readwrite(0xCA81/* | 0x0004*/); //FIFO9,SYNC,!ff,DR (FIFO level = 9) //ok
	rf12_spi_readwrite(0xCED4); //SYNC=2DD4; //ok
	rf12_spi_readwrite(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN //ok
	rf12_spi_readwrite(0x9850); //!mp,90kHz,MAX OUT //ok
	rf12_spi_readwrite(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0 //ok
	rf12_spi_readwrite(0xE000); //NOT USED //ok
	rf12_spi_readwrite(0xC800); //NOT USED //ok
	rf12_spi_readwrite(0xC040); //1.66MHz,2.2V //ok
	rf12_read_sr();

	rf12_status = RF12_STATUS_RX;
	rf12_fifo_reset();
	//printf_P(PSTR("[RF12] Configured as a receiver.\n"));
}

void rf12_tx_mode(long int baudrate)
{ //skopiowane z Lodz experimental engineering
	unsigned char baud_setting;
	if(baudrate < 3000)
	{
		baud_setting = 43103/baudrate - 1;
		baud_setting |= 0x80;
	}
	else
	{
		baud_setting = 344828/baudrate - 1;
		baud_setting &= 0x7F;
	}

	rf12_spi_readwrite(0x80D7/*& 0xFF3F buff off*/); //EL,EF,433band,12.0pF //ok  & 0xFF3F
	rf12_spi_readwrite(0x8239 & (~RF12_ET)); //!er,!ebb,ET,ES,EX,!eb,!ew,DC //ok
	rf12_spi_readwrite(0xA640); //frequency select - 434MHz //ok
	rf12_spi_readwrite(0xC600 | baud_setting); //4.8kbps //ok
	//rf12_spi_readwrite(0xC6FF); //0.3kbps //ok
	rf12_spi_readwrite(0x94A0); //VDI output,FAST,recv baseband bandwidth 134kHz, trans gain 0dBm (max), rssi treshold -103dBm (min) //ok
	rf12_spi_readwrite(0xC2AC); //AL,!ml,DIGital filter,DQD4 //ok
	rf12_spi_readwrite(0xCA81/* | 0x0004*/); //FIFO8,SYNChron pattern used,!ff,DR - no highly sensitove reset fifo //ok
	rf12_spi_readwrite(0xCED4); //SYNC=2DD4 //ok
	rf12_spi_readwrite(0xC483); //@PWR,NO ReSTRIC,!st,!fi,OE,EN //ok
	rf12_spi_readwrite(0x9850); //!mp,90kHz,MAX OUT //ok
	rf12_spi_readwrite(0xCC17); //OB1, COB0, LPX, Iddy, CDDIT CBW0 //ok
	rf12_spi_readwrite(0xE000); //NOT USED //ok
	rf12_spi_readwrite(0xC800); //NOT USED //ok
	rf12_spi_readwrite(0xC040); //1.66MHz,2.2V} //ok
	rf12_read_sr();

	preamble[0] = 0xAA;
	preamble[1] = 0xAA;

	pattern[0] = 0x2D;
	pattern[1] = 0xD4;

	rf12_status = RF12_STATUS_TX;
	//printf_P(PSTR("[RF12] Configured as a transmitter.\n"));
}

void rf12_send(char *content)
{
	unsigned char i=0;
	memcpy(&(snd_buf[4]),content,RF12_BUFF_SIZE);
	snd_buf[0] = preamble[0];
	snd_buf[1] = preamble[1];
	snd_buf[2] = pattern[0];
	snd_buf[3] = pattern[1];
	snd_buf[36] = preamble[0];
	snd_buf[37] = preamble[1];

	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));//preamble
	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));

	rf12_spi_readwrite(0x8239 | RF12_ET);//enable transmition circuit

	snd_counter = i;
	while(snd_counter < RF12_BUFF_SIZE + 6);

	rf12_spi_readwrite(0x8239 & (~RF12_ET) );//disable transmition circuit
}

/*
void rf12_send_pooling(char *content)
{
	unsigned char i=0;
	memcpy(&(snd_buf[4]),content,RF12_BUFF_SIZE);
	snd_buf[0] = preamble[0];
	snd_buf[1] = preamble[1];
	snd_buf[2] = pattern[0];
	snd_buf[3] = pattern[1];
	snd_buf[36] = preamble[0];
	snd_buf[37] = preamble[1];

	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));//preamble
	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));

	rf12_spi_readwrite(0x8239 | RF12_ET);//enable transmition circuit

	while(RF12_nIRQ_PORT & RF12_nIRQ);
	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));
	while(RF12_nIRQ_PORT & RF12_nIRQ);
	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));

	for(; i < RF12_BUFF_SIZE + 6; i++)
	{
		while(RF12_nIRQ_PORT & RF12_nIRQ);
		rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i]));
	}

	while(RF12_nIRQ_PORT & RF12_nIRQ);
	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));//dummy bytes
	while(RF12_nIRQ_PORT & RF12_nIRQ);
	rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[i++]));

	rf12_spi_readwrite(0x8239 & (~RF12_ET) );//disable transmition circuit
}
*/

char* rf12_receive()
{
	while(rcv_counter < RF12_BUFF_SIZE);

	memcpy(main_buf,rcv_buf,RF12_BUFF_SIZE);
	rcv_counter = 0;
	return main_buf;
}

ISR(INT0_vect)
{
	rf12_read_sr();
	switch(rf12_status)
	{
		case RF12_STATUS_RX:
			if(rcv_counter < RF12_BUFF_SIZE)
			{
				rcv_buf[rcv_counter++] = 0x00FF & rf12_spi_readwrite(0xB000);
				if(rcv_counter >= RF12_BUFF_SIZE) rf12_fifo_reset();
			}
			else
				rf12_fifo_reset(); //if we have unread packet we drop new incoming data
		break;

		case RF12_STATUS_TX:
			if(snd_counter < RF12_BUFF_SIZE + 6)
				rf12_spi_readwrite(0xB800 | (0x00FF & snd_buf[snd_counter++]));
		break;
	}
}
